package cn.enited.devtools.apiaggregator.repo.impl;

import cn.enited.devtools.apiaggregator.consts.CommonConst;
import cn.enited.devtools.apiaggregator.consts.ErrorCode;
import cn.enited.devtools.apiaggregator.entity.ApiAggObject;
import cn.enited.devtools.apiaggregator.exception.BizException;
import cn.enited.devtools.apiaggregator.repo.ApiConfRepository;
import cn.enited.devtools.apiaggregator.utils.NumUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import org.bson.Document;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Repository
public class ApiConfRepositoryImpl extends AbstractRepository<ApiAggObject> implements ApiConfRepository {
    @Override
    public Class<ApiAggObject> getEntityType() {
        return ApiAggObject.class;
    }

    private boolean apiNameExistInProject(String projectName, String apiName, Long bizId) {
        Criteria criteria = Criteria.where("name").is(apiName).and("projectName").is(projectName)
                .and(CommonConst.ENTITY.DEL_FLAG).is(false);
        if (NumUtil.isValidId(bizId)) {
            criteria = criteria.and(CommonConst.ENTITY.BIZ_ID).ne(bizId);
        }
        return exists(Query.query(criteria));
    }

    @Override
    public void save(ApiAggObject entity) throws BizException {
        if (apiNameExistInProject(entity.getProjectName(), entity.getName(), CommonConst.ZERO.LONG)) {
            throw new BizException(ErrorCode.EXIST.code(), "Api名称在当前项目下已存在");
        }
        entity.preCreate();
        getMongoTemplate().save(entity);
    }

    @Override
    public void update(ApiAggObject entity) throws BizException {
        if (apiNameExistInProject(entity.getProjectName(), entity.getName(), entity.getBizId())) {
            throw new BizException(ErrorCode.EXIST.code(), "Api名称在当前项目下已存在");
        }
        entity.preUpdate();
        Document document = entityToUpdateMap(entity, CommonConst.ENTITY.ID,
                CommonConst.ENTITY.BIZ_ID, CommonConst.ENTITY.CREATE_DATE, CommonConst.ENTITY.DEL_FLAG,
                "name", "projectId", "projectName");
        Update update = Update.fromDocument(document);
        getMongoTemplate().updateFirst(getBizIdQuery(entity.getBizId()), update, ApiAggObject.class);
    }

    @Override
    public Set<String> findAllCompletableApiNames(List<String> projectNames) {
        Criteria criteria = Criteria.where(CommonConst.ENTITY.DEL_FLAG).is(false);
        if (CollectionUtil.isNotEmpty(projectNames)) {
            criteria = criteria.and("projectName").in(projectNames);
        }
        Query query = Query.query(criteria);
        query.with(Sort.by(CommonConst.ENTITY.CREATE_DATE));
        query.fields().include("name", "projectName");
        List<ApiAggObject> entities = getMongoTemplate().find(query, ApiAggObject.class);
        return entities.parallelStream().map(obj -> buildCompletableApiName(obj.getProjectName(), obj.getName()))
                .collect(Collectors.toSet());
    }

    private String buildCompletableApiName(String projectName, String apiName) {
        return StrUtil.format("{}${}", projectName, apiName);
    }
}
